/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pl.tewi.jeeunit.junit4;

import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import pl.tewi.contexts.ApplicationServerContext;
import pl.tewi.exceptions.ApplicationServerContextException;
import pl.tewi.jeeunit.junit4.statements.BeginTransaction;
import pl.tewi.jeeunit.junit4.statements.EndTransaction;
import pl.tewi.jeeunit.junit4.statements.InjectResources;
import pl.tewi.jeeunit.junit4.statements.Login;
import pl.tewi.jeeunit.junit4.statements.Logout;

/**
 * Test runner wykorzystany do obsługi wstrzyknięć JEE do klas testowych.
 * Dzięki temu pola klas testowych mgą być opisane adnotacjami @EJB, @Inject, @Resource
 * @author Marcin Kwapisz
 */
class JeeUnitBlockJUnit4ClassRunner extends BlockJUnit4ClassRunner {

    /**
     * Kontekst serwera aplikacyjnego. Potrzebne do prawidłowego skonstruowania 
     * InitialContext (np. adres:host port, nazwy aplikacji itd) aby można się 
     * było odwoływać do komponentów
     * 
     */
    private ApplicationServerContext applicationServerContext;

    public JeeUnitBlockJUnit4ClassRunner(final Class<?> klass) throws InitializationError {
        super(klass);
    }

    /**
     * Tworzy obiekt klasy testowej wstrzykując jednocześnie wszystkie potrzebne zasoby 
     * na podstawie aktualnego kontekstu serwera aplikacyjnego i standardowych
     * adnotacji JavaEE v5/6.
     * @return obiekt klasy testu
     * @throws Exception <ul><li>{@link ApplicationServerContextException} gdy kontekst nie został ustawiony dla runnera</li></ul>
     */
    @Override
    protected Object createTest() throws Exception {
        Object testObject = super.createTest();
        return testObject;
    }

    @Override
    protected Statement methodBlock(final FrameworkMethod method) {
        return super.methodBlock(method);
    }

    /**
     * Główny kandydat do wpięcia obsługi adnotacji JEE.W metodzie tej jest dostepna
     * informacja o metodzie testowej i obiekt klasy testowej. Poprzez refleksję
     * można się dostać do pól klasy i je zainicjalizować
     * @param method
     * @param test obiekt klasy testowej
     * @return 
     */
    @Override
    protected Statement methodInvoker(final FrameworkMethod method, final Object test) {
        Statement statement = super.methodInvoker(method, test);
        statement = new EndTransaction(statement, applicationServerContext, method);
        statement = new Logout(statement, applicationServerContext);
        
        statement = new InjectResources(statement, applicationServerContext, method, test);
        statement = new BeginTransaction(statement, applicationServerContext, method);
        statement = new Login(statement, applicationServerContext, method);
        
        return statement;
    }

    void setApplictionServerContext(final ApplicationServerContext applicationServerContext) {
        this.applicationServerContext = applicationServerContext;
    }
}
